package com.agent.membership.service;

import com.agent.common.constant.CommonConstants;
import com.agent.common.entity.UserContext;
import com.agent.common.exception.BusinessException;
import com.agent.common.result.ApiResponse;
import com.agent.common.result.ResultCode;
import com.agent.common.utils.DateUtils;
import com.agent.common.utils.IdGenerator;
import com.agent.credit.api.feign.CreditFeignClient;
import com.agent.membership.entity.*;
import com.agent.membership.mapper.*;
import com.agent.payment.api.feign.PaymentFeignClient;
import com.agent.user.api.feign.UserFeignClient;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestClientException;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.List;

/**
 * 会员服务核心实现
 * @author Jeff_Wan
 * @description 提供会员订阅、升级、权益管理等服务
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class MembershipService {
    private final MembershipSubscriptionMapper subscriptionMapper;
    private final SubscriptionOrderMapper orderMapper;
    private final MembershipUpgradeMapper upgradeMapper;
    private final MembershipPlanMapper membershipPlanMapper;
    private final CreditFeignClient creditFeignClient;
    private final UserFeignClient userFeignClient;
    private final PaymentFeignClient paymentFeignClient;

    /**
     * 获取用户当前会员状态
     * @param userId 用户ID
     * @return 会员订阅信息
     */
    public MembershipSubscription getUserMembership(Long userId) {
        MembershipSubscription subscription = subscriptionMapper.findActiveSubscription(userId);
        if (subscription == null) {
            // 默认免费会员
            subscription = new MembershipSubscription();
            subscription.setUserId(userId);
            subscription.setPlanType(CommonConstants.MEMBER_FREE);
            subscription.setSubscriptionType(CommonConstants.SUBSCRIPTION_MONTHLY);
            subscription.setStatus("ACTIVE");
            subscription.setAutoRenew(false);
        }
        return subscription;
    }

    /**
     * 创建新订阅
     * @param userId 用户ID
     * @param planType 会员计划类型
     * @param subscriptionType 订阅类型
     * @param autoRenew 是否自动续费
     * @return 创建的订阅信息
     */
    @Transactional(rollbackFor = Exception.class)
    public MembershipSubscription createSubscription(Long userId, String planType,
                                                     String subscriptionType, boolean autoRenew) {
        // 检查用户是否已有活跃订阅
        MembershipSubscription existing = subscriptionMapper.findActiveSubscription(userId);
        if (existing != null && !"FREE".equals(existing.getPlanType())) {
            throw new BusinessException(ResultCode.MEMBERSHIP_ACTIVE_SUBSCRIPTION);
        }

        // 创建新订阅
        MembershipSubscription subscription = new MembershipSubscription();
        subscription.setId(IdGenerator.getInstance().nextId());
        subscription.setUserId(userId);
        subscription.setPlanType(planType);
        subscription.setSubscriptionType(subscriptionType);
        subscription.setStartDate(LocalDateTime.now(ZoneOffset.UTC));
        subscription.setExpiryDate(calculateExpiryDate(subscriptionType));
        subscription.setAutoRenew(autoRenew);
        subscription.setStatus("ACTIVE");
        subscriptionMapper.insert(subscription);

        // 更新用户服务
        updateUserMembership(userId, planType, subscriptionType);

        return subscription;
    }

    /**
     * 升级会员计划
     * @param userId 用户ID
     * @param newPlanType 新会员计划类型
     * @param newSubscriptionType 新订阅类型
     * @return 升级后的会员订阅信息
     */
    @Transactional(rollbackFor = Exception.class)
    public MembershipSubscription upgradeMembership(Long userId, String newPlanType,
                                                    String newSubscriptionType) {
        MembershipSubscription current = getUserMembership(userId);

        // 验证是否可以升级
        validateUpgrade(current, newPlanType, newSubscriptionType);

        // 计算积分抵扣金额
        BigDecimal creditDeduction = calculateCreditDeduction(current);

        // 计算实际支付金额
        BigDecimal upgradeAmount = calculateUpgradeAmount(
                current, newPlanType, newSubscriptionType, creditDeduction);

        // 创建升级记录
        recordUpgradeHistory(userId, current, newPlanType, newSubscriptionType, creditDeduction, upgradeAmount);

        // 更新会员订阅
        MembershipSubscription newSubscription = new MembershipSubscription();
        newSubscription.setId(IdGenerator.getInstance().nextId());
        newSubscription.setUserId(userId);
        newSubscription.setPlanType(newPlanType);
        newSubscription.setSubscriptionType(newSubscriptionType);
        newSubscription.setStartDate(LocalDateTime.now(ZoneOffset.UTC));
        newSubscription.setExpiryDate(calculateExpiryDate(newSubscriptionType));
        newSubscription.setAutoRenew(true);
        newSubscription.setStatus("ACTIVE");
        subscriptionMapper.insert(newSubscription);

        // 更新原订阅状态
        current.setStatus("CANCELLED");
        subscriptionMapper.updateById(current);

        // 更新用户服务
        updateUserMembership(userId, newPlanType, newSubscriptionType);

        return newSubscription;
    }

    /**
     * 处理自动续费
     * @param subscription 需要续费的订阅
     */
    @Transactional(rollbackFor = Exception.class)
    public void processAutoRenewal(MembershipSubscription subscription) {
        if (!subscription.getAutoRenew()) {
            return;
        }

        try {
            // 创建续费订单
            SubscriptionOrder order = createRenewalOrder(subscription);

            // 调用支付服务处理支付
            boolean paymentSuccess = paymentFeignClient.processPayment(
                    subscription.getUserId(),
                    order.getOrderAmount(),
                    "SUBSCRIPTION_RENEWAL"
            ).getData();

            if (paymentSuccess) {
                handleSuccessfulRenewal(subscription, order);
            } else {
                handleFailedRenewal(subscription, order);
            }
        } catch (Exception e) {
            log.error("续费处理异常: userId={}", subscription.getUserId(), e);
            handleRenewalException(subscription);
        }
    }

    /**
     * 验证用户是否有权限使用特定模型
     * @param userContext 用户上下文
     * @param modelName 模型名称
     * @return 是否有权限
     */
    public boolean validateModelAccess(UserContext userContext, String modelName) {
        // 免费用户只能使用基础模型
        if (userContext.isFreeUser()) {
            return CommonConstants.MODEL_SEEDANCE_LITE.equals(modelName) ||
                    CommonConstants.MODEL_GPT_IMAGE.equals(modelName);
        }

        // Basic月计划不能使用Veo高级版
        if (userContext.isBasicUser() &&
                CommonConstants.SUBSCRIPTION_MONTHLY.equals(userContext.getSubscriptionType()) &&
                CommonConstants.MODEL_VEO_PREMIUM.equals(modelName)) {
            return false;
        }

        // 其他会员可以使用所有模型
        return true;
    }

    // ================ 私有方法 ================ //

    /**
     * 创建续费订单
     */
    private SubscriptionOrder createRenewalOrder(MembershipSubscription sub) {
        SubscriptionOrder order = new SubscriptionOrder();
        order.setId(IdGenerator.getInstance().nextId());
        order.setUserId(sub.getUserId());
        order.setSubscriptionId(sub.getId());
        order.setOrderAmount(calculateRenewalAmount(sub));
        order.setPaymentMethod("ASIABILL");
        order.setOrderStatus("PENDING");
        order.setCreatedAt(LocalDateTime.now(ZoneOffset.UTC));
        orderMapper.insert(order);
        return order;
    }

    /**
     * 处理续费成功
     */
    private void handleSuccessfulRenewal(MembershipSubscription sub,
                                         SubscriptionOrder order) {
        // 更新订单状态
        order.setOrderStatus("PAID");
        order.setPaymentDate(LocalDateTime.now(ZoneOffset.UTC));
        orderMapper.updateById(order);

        // 更新订阅有效期(UTC时间)
        LocalDateTime newExpiry = calculateExpiryDate(sub.getSubscriptionType());
        sub.setExpiryDate(newExpiry);
        subscriptionMapper.updateById(sub);

        // 更新用户服务会员信息
        updateUserMembership(sub.getUserId(), sub.getPlanType(), sub.getSubscriptionType());

        // 发放会员积分
        creditFeignClient.grantSubscriptionCredits(
                sub.getUserId(),
                sub.getPlanType(),
                sub.getSubscriptionType()
        );
    }

    /**
     * 处理续费失败
     */
    private void handleFailedRenewal(MembershipSubscription sub,
                                     SubscriptionOrder order) {
        order.setOrderStatus("FAILED");
        orderMapper.updateById(order);

        // 关闭自动续费
        sub.setAutoRenew(false);
        subscriptionMapper.updateById(sub);

        // 发送通知
//        notificationService.sendRenewalFailedAlert(
//                sub.getUserId(),
//                sub.getPlanType(),
//                order.getOrderAmount()
//        );
    }

    /**
     * 处理续费异常
     */
    private void handleRenewalException(MembershipSubscription sub) {
        // 标记为需要人工干预
        sub.setAutoRenew(false);
        subscriptionMapper.updateById(sub);

        // 发送系统警报
//        notificationService.sendSystemAlert(
//                "续费处理失败: userId=" + sub.getUserId()
//        );
    }

    /**
     * 计算到期日期(UTC)
     */
    private LocalDateTime calculateExpiryDate(String subscriptionType) {
        LocalDateTime nowUTC = LocalDateTime.now(ZoneOffset.UTC);
        return CommonConstants.SUBSCRIPTION_YEARLY.equals(subscriptionType) ?
                nowUTC.plusYears(1) : nowUTC.plusMonths(1);
    }

    /**
     * 验证是否可以升级
     * @param current
     * @param newPlanType
     * @param newSubscriptionType
     */
    private void validateUpgrade(MembershipSubscription current, String newPlanType, String newSubscriptionType) {
        // 不能降级
        if (isDowngrade(current.getPlanType(), newPlanType)) {
            throw new BusinessException(ResultCode.MEMBERSHIP_DOWNGRADE_NOT_ALLOWED);
        }

        // 年计划不能降级为月计划
        if (CommonConstants.SUBSCRIPTION_YEARLY.equals(current.getSubscriptionType()) &&
                CommonConstants.SUBSCRIPTION_MONTHLY.equals(newSubscriptionType)) {
            throw new BusinessException(ResultCode.MEMBERSHIP_DOWNGRADE_NOT_ALLOWED);
        }
    }

    /**
     * 降级判断
     * @param currentPlan
     * @param newPlan
     * @return
     */
    private boolean isDowngrade(String currentPlan, String newPlan) {
        // 会员等级排序：FREE < BASIC < PRO < MAX
        String[] levels = {"FREE", "BASIC", "PRO", "MAX"};
        int currentIndex = -1;
        int newIndex = -1;

        for (int i = 0; i < levels.length; i++) {
            if (levels[i].equals(currentPlan)) currentIndex = i;
            if (levels[i].equals(newPlan)) newIndex = i;
        }

        return newIndex < currentIndex;
    }

    /**
     * 计算积分抵扣金额
     * @param current
     * @return
     */
    private BigDecimal calculateCreditDeduction(MembershipSubscription current) {
        // 获取用户剩余积分
        ApiResponse<Integer> remainingCredits = creditFeignClient.getUserCredits(current.getUserId());

        if (remainingCredits.getCode() != ResultCode.SUCCESS.getCode() || remainingCredits.getData() == null) {
            throw new BusinessException(ResultCode.USER_NOT_EXIST, "Points inquiry failed");
        }

        // 计算积分价值
        BigDecimal creditValue;
        if (CommonConstants.SUBSCRIPTION_YEARLY.equals(current.getSubscriptionType())) {
            BigDecimal yearlyPrice = getPlanPrice(current.getPlanType(), CommonConstants.SUBSCRIPTION_YEARLY);
            int yearlyCredits = getPlanCredits(current.getPlanType(), CommonConstants.SUBSCRIPTION_YEARLY);
            creditValue = yearlyPrice.divide(
                    BigDecimal.valueOf(yearlyCredits), 4, RoundingMode.HALF_UP);
        } else {
            BigDecimal monthlyPrice = getPlanPrice(current.getPlanType(), CommonConstants.SUBSCRIPTION_MONTHLY);
            int monthlyCredits = getPlanCredits(current.getPlanType(), CommonConstants.SUBSCRIPTION_MONTHLY);
            creditValue = monthlyPrice.divide(
                    BigDecimal.valueOf(monthlyCredits), 4, RoundingMode.HALF_UP);
        }

        return creditValue.multiply(BigDecimal.valueOf(remainingCredits.getData()));
    }

    /**
     * 计算实际支付金额
     * @param current
     * @param newPlanType
     * @param newSubscriptionType
     * @param creditDeduction
     * @return
     */
    private BigDecimal calculateUpgradeAmount(MembershipSubscription current, String newPlanType,
                                              String newSubscriptionType, BigDecimal creditDeduction) {
        BigDecimal newPlanPrice = getPlanPrice(newPlanType, newSubscriptionType);
        return newPlanPrice.subtract(creditDeduction).max(BigDecimal.ZERO);
    }

    /**
     * 创建升级记录
     * @param userId
     * @param current
     * @param newPlanType
     * @param newSubscriptionType
     * @param creditDeduction
     * @param upgradeAmount
     */
    private void recordUpgradeHistory(Long userId, MembershipSubscription current, String newPlanType,
                                      String newSubscriptionType, BigDecimal creditDeduction,
                                      BigDecimal upgradeAmount) {
        MembershipUpgrade upgrade = new MembershipUpgrade();
        upgrade.setId(IdGenerator.getInstance().nextId());
        upgrade.setUserId(userId);
        upgrade.setFromPlan(current.getPlanType());
        upgrade.setToPlan(newPlanType);
        upgrade.setFromSubscription(current.getSubscriptionType());
        upgrade.setToSubscription(newSubscriptionType);
        upgrade.setCreditDeduction(creditDeduction);
        upgrade.setUpgradeAmount(upgradeAmount);
        upgrade.setUpgradeDate(LocalDateTime.now(ZoneOffset.UTC));
        upgradeMapper.insert(upgrade);
    }

    private BigDecimal calculateRenewalAmount(MembershipSubscription subscription) {
        return getPlanPrice(subscription.getPlanType(), subscription.getSubscriptionType());
    }

    /**
     * 获取计划金额
     * @param planType 套餐类型
     * @param subscriptionType 订阅类型
     * @return 套餐价格
     */
    private BigDecimal getPlanPrice(String planType, String subscriptionType) {
        MembershipPlan plan = membershipPlanMapper.findByPlanAndSubscription(planType, subscriptionType);
        if (plan == null) {
            throw new BusinessException(ResultCode.INVALID_SUBSCRIPTION_PLAN,
                    "Package configuration not found: " + planType + "-" + subscriptionType);
        }
        return plan.getPrice();
    }

    /**
     * 获取计划总积分数量
     * @param planType 套餐类型
     * @param subscriptionType 订阅类型
     * @return 套餐总积分
     */
    private int getPlanCredits(String planType, String subscriptionType) {
        MembershipPlan plan = membershipPlanMapper.findByPlanAndSubscription(planType, subscriptionType);
        if (plan == null) {
            throw new BusinessException(ResultCode.INVALID_SUBSCRIPTION_PLAN,
                    "Package configuration not found: " + planType + "-" + subscriptionType);
        }
        return plan.getTotalCredits();
    }

    /**
     * 更新用户会员信息
     */
    @Retryable(value = RestClientException.class,
            maxAttempts = 3,
            backoff = @Backoff(delay = 1000))
    public void updateUserMembership(Long userId, String planType, String subscriptionType) {
        userFeignClient.updateMembership(userId, planType, subscriptionType);
    }

    /**
     * 初始化会员订阅
     * @param userId 用户ID
     */
    public void initMembership(Long userId) {
        MembershipSubscription existing = subscriptionMapper.selectByUserId(userId);
        if (existing != null) {
            return;
        }

        MembershipSubscription membership = new MembershipSubscription();
        membership.setId(IdGenerator.getInstance().nextId());
        membership.setUserId(userId);
        membership.setPlanType(CommonConstants.MEMBER_FREE);
        membership.setStartDate(LocalDateTime.now(ZoneOffset.UTC));
        // 免费会员长期有效
        membership.setExpiryDate(LocalDateTime.now(ZoneOffset.UTC).plusYears(100));
        membership.setAutoRenew(false);
        subscriptionMapper.insert(membership);
    }

    /**
     * 获取用户会员信息
     * @param userId 用户ID
     * @return 会员信息
     */
    public MembershipSubscription getUserMembershipCredit(Long userId) {
        return subscriptionMapper.selectByUserId(userId);
    }

    /**
     * 获取所有会员套餐配置
     * @return 套餐列表
     */
    public List<MembershipPlan> getAllMembershipPlansCredit() {
        return membershipPlanMapper.selectList(null);
    }

    /**
     * 取消自动续费
     * @param userId 用户ID
     * @return 操作结果
     */
    public boolean cancelAutoRenew(Long userId) {
        MembershipSubscription subscription =getUserMembership(userId);
        subscription.setAutoRenew(false);
        int i = subscriptionMapper.updateById(subscription);
        return i > 0;
    }
}